#ifndef __DIM_SUM_MMU_H
#define __DIM_SUM_MMU_H

#include <dim-sum/stddef.h>
#include <asm/processor.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>

#include <asm/memory.h>
#include <asm/mmu.h>

void mmu_set_tlb(struct mmu_desc* mmu);
int mmu_ttbl_fault(struct mmu_walk_info* info);
int mmu_ttbl_permission(struct mmu_walk_info* info);
int mmu_complete_map(struct mmu_walk_info* info);
int mmu_kernel_rw_map(struct mmu_walk_info* info);
int mmu_cutoff_vaddr(struct mmu_walk_info* info);
int mmu_connect_vaddr(struct mmu_walk_info* info);
int mmu_unmap_range(struct mmu_walk_info* info);
int mmu_find_ttbl(struct mmu_walk_info* info);
int mmu_map_range(struct mmu_walk_info *info);
int mmu_mprotect_range(struct mmu_walk_info* info);
int mmu_dirty_range(struct mmu_walk_info *info);
int mmu_clean_tbl(struct mmu_walk_info* info);
int mmu_create(struct process_desc* proc);
int mmu_exit(struct process_desc* proc, struct mem_desc* m);
int mmu_set_info_prot(struct mmu_walk_info *info, u64 access);

static inline phys_addr_t mmu_walk_info_l4_phyadr(struct mmu_walk_info* info)
{
	if (!info)
		return (phys_addr_t)NULL;
	if (!info->out_l4wptr)
		return (phys_addr_t)NULL;
	return (phys_addr_t)mmu_l4_val_paddr(mmu_l4_value(info->out_l4wptr));
}

static inline int mmu_walk_info_set_prot(struct mmu_walk_info* info, unsigned long prot)
{
	if (!info)
		return -EINVAL;
	return arch_mmu_walk_info_set_prot(info, prot);
}


static inline void attach_to_pt_l2(pt_l2_t *pt_l2, pt_l3_t *pt_l3)
{
	set_pt_l2(pt_l2, pt_l2(linear_virt_to_phys(pt_l3) | PT_L3_TYPE_TABLE));
}

static inline void __attach_to_pt_l3(pt_l3_t *pmdp, phys_addr_t pte,
				  pt_l3_val_t prot)
{
	set_pt_l3(pmdp, pt_l3(pte | prot));
}

static inline void
attach_to_pt_l3(pt_l3_t *pmdp, pt_l4_val_t *ptep)
{
	__attach_to_pt_l3(pmdp, linear_virt_to_phys(ptep), PT_L3_TYPE_TABLE);
}

#endif /* __DIM_SUM_MMU_H */
